﻿package org.nickro.project.utils {
	import flash.display.DisplayObject;
	import flash.display.Bitmap;
    import flash.display.BitmapData;
	import flash.display.PixelSnapping;
	import flash.display.Sprite;
	import flash.geom.Rectangle;
    import flash.geom.Point;
	import flash.geom.ColorTransform;
	import flash.geom.Matrix;
    import flash.utils.getDefinitionByName;

    public class DisplayObjects {

        public static const ORIGIN_POINT:Point = new Point(0, 0);

        public function DisplayObjects(){
            throw (new Error("ERROR org.nickro.project.utils.DisplayObjects constructor: Class never intended to be instantiated"));
        }
		/**
		 * 限制显示对象在rect矩形框中移动
		 * @param	obj
		 * @param	rect
		 */
        public static function moveWithinRect(obj:DisplayObject, rect:Rectangle):void{
            var bounds:Rectangle = obj.getBounds(obj.parent);
            if (bounds.left < rect.left){
                obj.x = (obj.x + (rect.left - bounds.left));
            } else {
                if (bounds.right > rect.right){
                    obj.x = (obj.x - (bounds.right - rect.right));
                };
            };
            if (bounds.top < rect.top){
                obj.y = (obj.y + (rect.top - bounds.top));
            } else {
                if (bounds.bottom > rect.bottom){
                    obj.y = (obj.y - (bounds.bottom - rect.bottom));
                };
            };
        }
		/**
		 * 移动显示对象到指定矩形框
		 * @param	obj
		 * @param	rect
		 * @param	centered
		 */
		public static function moveToRect(obj:DisplayObject, rect:Rectangle, centered:Boolean=true):void{
            var bounds:Rectangle = obj.getBounds(obj);
            obj.x = (rect.x - (bounds.left * obj.scaleX));
            obj.y = (rect.y - (bounds.top * obj.scaleY));
            if (centered){
                bounds = obj.getBounds(obj.parent);
                obj.x = (obj.x + ((rect.width - bounds.width) / 2));
                obj.y = (obj.y + ((rect.height - bounds.height) / 2));
            };
        }
		/**
		 * 限制显示对象的大小为矩形框区域
		 * @param	obj
		 * @param	rect
		 * @param	enlarge
		 */
        public static function limitSizeToRect(obj:DisplayObject, rect:Rectangle, enlarge:Boolean=false):void{
            var scale:*;
            var obj = obj;
            var rect = rect;
            var enlarge = enlarge;
            var object = obj;
            with (object) {
                if ((width > rect.width) || (enlarge)){
                    width = rect.width;
                };
                if ((height > rect.height) || (enlarge)){
                    height = rect.height;
                };
                if (scaleX != scaleY){
                    scale = Math.min(scaleX, scaleY);
                    scaleX = scale;
                    scaleY = scale;
                };
            };
        }
		/**
		 * 移动并限制显示对象在指定的矩形区域
		 * @param	obj
		 * @param	rect
		 * @param	centered
		 */
		public static function moveAndLimitSizeToRect(obj:DisplayObject, rect:Rectangle, centered:Boolean=true):void{
            limitSizeToRect(obj, rect);
            moveToRect(obj, rect, centered);
        }
		/**
		 * 替换显示对象
		 * @param	oldObj
		 * @param	newObj
		 */
        public static function replaceChild(oldObj:DisplayObject, newObj:DisplayObject):void{
            var i:int;
            var theParent:DisplayObjectContainer = oldObj.parent;
            if (theParent is DisplayObjectContainer){
                i = theParent.getChildIndex(oldObj);
                theParent.removeChild(oldObj);
                theParent.addChildAt(newObj, i);
            } else {
                throw (new Error("No parent found in DisplayObjects.replaceChild()"));
            };
        }
		/**
		 * 添加图像
		 * @param	className
		 * @param	pixelSnapping
		 * @param	smoothing
		 * @return
		 */
		public static function attachBitmap(className:String, pixelSnapping:String=null, smoothing:Boolean=true):Bitmap{
            var classRef:Class = (getDefinitionByName(className) as Class);
            var bitmapData:BitmapData = BitmapData(new classRef(0, 0));
            return (new Bitmap(bitmapData, ((pixelSnapping == null)) ? PixelSnapping.AUTO : pixelSnapping, smoothing));
        }
		/**
		 * 在指定的显示对象的上层添加一个矩形大小遮罩
		 * @param	obj
		 * @param	rect
		 */
		public static function addRectMaskAbove(obj:DisplayObject, rect:Rectangle):void{
            var maskSprite:Sprite = new Sprite();
            maskSprite.graphics.beginFill(0xFF0000);
            maskSprite.graphics.drawRect(rect.x, rect.y, rect.width, rect.height);
            var theParent:DisplayObjectContainer = obj.parent;
            theParent.addChildAt(maskSprite, (theParent.getChildIndex(obj) + 1));
            obj.mask = maskSprite;
        }
		
        public static function createInverseMaskedSprite(image_src:DisplayObject, mask_src:DisplayObject, width:Number, height:Number, holeX:Number=0, holeY:Number=0):Sprite{
            var bmp:Bitmap = createInverseMaskedBitmap(image_src, mask_src, width, height, holeX, holeY);
            var sprite:Sprite = new Sprite();
            sprite.addChild(bmp);
            sprite.cacheAsBitmap = true;
            return (sprite);
        }
		public static function createInverseMaskedBitmap(image_src:DisplayObject, mask_src:DisplayObject, width:Number, height:Number, holeX:Number=0, holeY:Number=0):Bitmap{
            var mask_bmpData:BitmapData = new BitmapData(width, height, true, 4294967295);
            var invert_ct:ColorTransform = new ColorTransform(0, 0, 0, 1);
            var matrix:Matrix = new Matrix();
            matrix.translate(holeX, holeY);
            mask_bmpData.draw(mask_src, matrix, invert_ct);
            var bounds:Rectangle = new Rectangle(0, 0, width, height);
            mask_bmpData.threshold(mask_bmpData, bounds, ORIGIN_POINT, "<", 4294967295, 0);
            var result_bmpData:BitmapData = new BitmapData(width, height, true, 0);
            result_bmpData.draw(image_src);
            result_bmpData.copyPixels(result_bmpData, bounds, ORIGIN_POINT, mask_bmpData, ORIGIN_POINT);
            return (new Bitmap(result_bmpData));
        }
		
        public static function localToLocal(fromObj:DisplayObject, toObj:DisplayObject, pt:Point):Point{
            if (!(pt is Point)){
                pt = ORIGIN_POINT;
            };
            pt = fromObj.localToGlobal(pt);
            pt = toObj.globalToLocal(pt);
            return (pt);
        }
		
        public static function getNamedInstances(container:DisplayObject, prefix:String, suffix:String="", ID:int=0, lastID:int=-1):Array{
            var nextName:String;
            var found:Boolean;
            var instanceList:Array = [];
            var lastDefined = (lastID >= 0);
            do  {
                nextName = (prefix + ID + suffix);
                found = ((container.hasOwnProperty(nextName)) && ((container[nextName] is DisplayObject)));
                if (found){
                    instanceList[ID] = container[nextName];
                };
                ID++;
            } while ((lastDefined) ? (ID <= lastID) : found);
            return (instanceList);
        }
        
        /**
         * 显示对象紧贴像素
         * @param	obj
         * @param	useRect
         */
        public static function snapToPixels(obj:DisplayObject, useRect:Boolean=false):void{
            var rect:*;
            var rectWidth:*;
            var rectHeight:*;
            var obj = obj;
            var useRect = useRect;
            var object = obj;
            with (object) {
                if (useRect){
                    rect = obj.getRect(obj.parent);
                    rectWidth = rect.width;
                    rectHeight = rect.height;
                    width = (Math.round(rectWidth) + (width - rectWidth));
                    height = (Math.round(rectHeight) + (height - rectHeight));
                } else {
                    width = Math.round(width);
                    height = Math.round(height);
                };
                x = Math.round(x);
                y = Math.round(y);
            };
        }
        
    }
}
